﻿using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using System.Linq;
using T.FAS.Runtime.Base.Common;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.Page.Dao.Teable
{
    public class MultiDimensionTableUtil
    {        
        public Dictionary<string, string> PostTeable(Dictionary<string, object> formData, Dictionary<string, string> teableConfig)
        {
            Dictionary<string, string> dic = null;
            string teableUrl = string.Empty;
            string authorization = string.Empty;
            if (teableConfig != null)
            {
                teableUrl = teableConfig["TeableUrl"];
                authorization = teableConfig["TeableAuthorization"];
            }
            else {
                string fasTeableConfig = ConfigUtil.Instance.FasTeableConfig;// 开通端口ACL
                if (string.IsNullOrEmpty(fasTeableConfig) == false)
                {
                    Dictionary<string, string> configDic = JsonConvert.DeserializeObject<Dictionary<string, string>>(fasTeableConfig);
                    teableUrl = configDic["TeableUrl"];
                    authorization = configDic["TeableAuthorization"];
                }
            }
            using (var httpClient = new HttpClient())
            {                
                if(string.IsNullOrEmpty(teableUrl) == false && string.IsNullOrEmpty(authorization) == false)
                {
                    string formDataStr = JsonConvert.SerializeObject(formData);
                    LogUtil.Log($"formData:{formDataStr}", "Teable");
                    string url = $"{teableUrl}/api/base/public/table/";
                    // 添加 Authorization 头，示例为 Bearer 令牌
                    httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authorization);
                    httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                    HttpContent content = new StringContent(formDataStr, Encoding.UTF8, "application/json");
                    try
                    {
                        using (var response = httpClient.PostAsync(url, content).Result)
                        {
                            try
                            {
                                // LogUtil.Log($"response:{JsonConvert.SerializeObject(response)}", "Teable");
                                response.EnsureSuccessStatusCode();
                                var result = response.Content.ReadAsStringAsync().Result;
                                Dictionary<string, object> resultDic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
                                // Todo，失败处理
                                // 临时处理
                                dic = new Dictionary<string, string>();
                                dic["tableid"] = (string)resultDic["id"];
                                JArray views = (JArray)resultDic["views"];
                                dic["viewid"] = (string)views[0]["id"];
                            }
                            catch (Exception ex)
                            {
                                LogUtil.Log($"exception1:{ex.ToString()}", "Teable");
                                throw ex;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogUtil.Log($"teableUrl:{teableUrl}, authorization:{authorization}", "Teable");
                        LogUtil.Log($"formData:{formDataStr}", "Teable");
                        LogUtil.Log($"exception:{ex.ToString()}", "Teable");
                        throw ex;
                    }
                }
                
            }
            return dic;
        }

        public Tuple<string, string, string> GetTeableFieldType(DataColumn dataColumn, DataQueryColumn dataQueryColumn, string fieldType = "")
        {
            if (dataColumn != null)
            {
                string dataType = dataColumn.DataType;
                if (dataColumn.RelatedDataObjectPrimaryKey != null)
                {
                    dataType = dataColumn.RelatedDataObjectPrimaryKey.DataType;
                }
                switch (dataType)
                {
                    case "Varchar":
                        if (dataColumn.Length > 1000)
                        {
                            return new Tuple<string, string, string>(getTeableType(fieldType,"longText"), "string", "TEXT");
                        }
                        return new Tuple<string, string, string>(getTeableType(fieldType, "singleLineText"), "string", "TEXT");
                    case "Varchar(max)":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "longText"), "string", "TEXT");
                    case "TinyInt":
                    case "SmallInt":
                    case "Int":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "number"), "number", "INTEGER");
                    case "BigInt":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "number"), "number", "BIGINT");
                    case "Decimal":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "number"), "number", "DECIMAL");
                    case "Date":
                    case "Time":
                    case "DateTime":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "date"), "string", "DATE");
                    case "Timestamp":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "date"), "string", "TIMESTAMP");
                    case "Varbinary":
                    case "Binary":
                    case "Varbinary(max)":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "longText"), "string", "BYTEA");
                    case "Bit":
                        return new Tuple<string, string, string>(getTeableType(fieldType, "checkbox"), "boolean", "BIT");
                    default:
                        return new Tuple<string, string, string>(getTeableType(fieldType, "singleLineText"), "string", "TEXT");
                }
            }
            else if (dataQueryColumn != null)
            {
                switch (dataQueryColumn.ColumnDataType)
                {
                    case "String":
                        return new Tuple<string, string, string>("singleLineText", "string", "TEXT");
                    case "Int":
                    case "Long":
                        return new Tuple<string, string, string>("number", "number", "INTEGER");
                    case "Decimal":
                        return new Tuple<string, string, string>("number", "number", "DECIMAL");
                    case "Date":
                    case "Time":
                    case "DateTime":
                        return new Tuple<string, string, string>("date", "string", "DATE");
                    case "Timestamp":
                        return new Tuple<string, string, string>("date", "string", "TIMESTAMP");
                    case "Binary":
                        return new Tuple<string, string, string>("longText", "string", "BYTEA");
                    case "Boolean":
                        return new Tuple<string, string, string>("checkbox", "boolean", "BOOLEAN");
                    default:
                        return new Tuple<string, string, string>("singleLineText", "string", "TEXT");
                }
            }
            return new Tuple<string, string, string>("singleLineText", "string", "TEXT");
        }
        public List<Dictionary<string, object>> InitFormDataColumns()
        {
            var result = new List<Dictionary<string, object>>();
            //result.Add(GetField("id", "主键ID", new Tuple<string, string, string>("singleLineText", "string", "TEXT"), true));
            result.Add(GetField("code", "编号", new Tuple<string, string, string>("singleLineText", "string", "VARCHAR")));
            result.Add(GetField("name", "名称", new Tuple<string, string, string>("singleLineText", "string", "TEXT")));
            //result.Add(GetField("creator", "创建人", new Tuple<string, string, string>("singleLineText", "string", "TEXT")));
            result.Add(GetField("creatorname", "创建人姓名", new Tuple<string, string, string>("singleLineText", "string", "TEXT")));
            //result.Add(GetField("createtime", "创建时间", new Tuple<string, string, string>("date", "string", "DATE")));
            //result.Add(GetField("lastmodifier", "最后修改人", new Tuple<string, string, string>("singleLineText", "string", "TEXT"), false, false));
            result.Add(GetField("lastmodifiername", "最后修改人姓名", new Tuple<string, string, string>("singleLineText", "string", "TEXT"), false, true, false));
            //result.Add(GetField("lastmodifytime", "最后修改时间", new Tuple<string, string, string>("date", "string", "DATE"), false, true, false));
            return result;
        }
        public Dictionary<string, string> GetInitFieldMapping()
        {
            return new Dictionary<string, string> { { "code", "Code"}, { "name", "Name" }, { "creatorname", "CreatorName" }, { "lastmodifiername", "LastModifierName" } };

        }
        public Dictionary<string, object> GetField(string fieldName, string displayName, Tuple<string, string, string> teableType, bool isPrimary = false, bool recordRead = true, bool recordCreate = true)
        {
            return new Dictionary<string, object> {
                                { "name", displayName },
                                { "type", teableType.Item1 },
                                { "description", displayName },
                                { "isLookup", false },
                                { "notNull", isPrimary },
                                { "unique", isPrimary },
                                { "isPrimary", isPrimary },
                                { "isComputed", false },
                                { "isPending", false },
                                { "hasError", false },
                                { "cellValueType",  teableType.Item2 },
                                { "isMultipleCellValue", false},
                                { "dbFieldType",  teableType.Item3 },
                                { "dbFieldName", fieldName },
                                { "recordRead", recordRead },
                                { "recordCreate", recordCreate }
                            };
        }

        private string getTeableType(string fieldType, string type) { 
            return string.IsNullOrEmpty(fieldType)?type:fieldType;
        }
    }
}
